/*
 * BestSolutionExchange.cpp
 *
 *  Created on: 31/01/2014
 *      Author: root
 */

#include "BestSolutionExchange.h"
#include <iostream>
#include "Utils.h"
//sacar a archivo de configuraciones
#define BEST_SOLUTION_EXCHANGE_DELAY 2 //???

using namespace std;

extern int rank, size;
extern Tuple * bestSolution;
extern pthread_mutex_t best_solution_mutex;
extern bool end;
extern pthread_mutex_t end_flag_mutex;

int BestSolutionExchange(){

	//cout<<"Comenzando BestSolutionExchange, rank = "<<rank<<endl;
	bool exitCondition;
	Tuple * ownBS;
	int currentBSCost;
	int currentBSOwner;

	MPI_Comm bestSolutionComm;
	MPI_Comm_dup(MPI_COMM_WORLD,&bestSolutionComm);
	//cout<<"BestSolutionExchange: Entrando en el do-while BestSolutionExchange, rank = "<<rank<<endl;
	do{

		sleep(BEST_SOLUTION_EXCHANGE_DELAY);

		pthread_mutex_lock(&best_solution_mutex);
		ownBS = bestSolution->copy();
		pthread_mutex_unlock(&best_solution_mutex);

		int recvBuff[size][Tuple::tuplesIntSize];
		int sizeBuff = sizeof(int) * Tuple::tuplesIntSize * size;

		//cout<<"BestSolutionExchange: Before Allgather size: "<<size<<" sizeBuff: "<<sizeBuff<<" tuplesIntSize: "<<Tuple::tuplesIntSize<<" rank: "<<rank<<endl;
		//cout<<"ownBS is NULL? "<<(ownBS->getArray() == NULL)<<" rank: "<<rank<<endl;
		//Se distribuyen las mejores souciones de los procesos
		//cout<<"BestSolutionExchange: BEFORE Allgather, rank: "<<rank<<endl;

		int error = MPI_Allgather(ownBS->getArray(), Tuple::tuplesIntSize,MPI_INT,
				recvBuff, Tuple::tuplesIntSize,MPI_INT,bestSolutionComm);

		//cout<<"BestSolutionExchange: AFTER Allgather, error: "<<error<<" rank: "<<rank<<endl;
		currentBSCost = ownBS->cost();
		currentBSOwner = 0;
		//cout<<"BestSolutionExchange: por obtener los datos del recvBuff, rank: "<<rank<<endl;
		for(int i = 0; i < size; i++){
			if (Tuple::GetCostFromTupleArray(recvBuff[i]) < currentBSCost){
				currentBSCost = Tuple::GetCostFromTupleArray(recvBuff[i]);
				currentBSOwner = i;
			}
		}
		//cout<<"BestSolutionExchange: comparando los costos, rank: "<<rank<<endl;
		if (currentBSCost < ownBS->cost()) {
			//cout<<"BestSolutionExchange: entro al if (currentBSCost < ownBS->cost()), rank: "<<rank<<endl;
			pthread_mutex_lock(&best_solution_mutex);
			delete bestSolution;
			bestSolution = new Tuple(Tuple::tuplesIntSize,recvBuff[currentBSOwner]);
			pthread_mutex_unlock(&best_solution_mutex);
			//cout<<"BestSolutionExchange: unlock bestSolution, rank: "<<rank<<endl;

		}

		delete ownBS;

		pthread_mutex_lock(&end_flag_mutex);
		exitCondition = end;
		pthread_mutex_unlock(&end_flag_mutex);

	}while(!exitCondition);

	MPI_Comm_free(&bestSolutionComm);

	return 0;
}


